<?php
declare (strict_types=1);

namespace app\admin\validate\dev;

use app\common\Constants;
use think\facade\Log;
use think\helper\Str;
use think\Validate;
use app\admin\model\dev\Menu as MenuModel;

class Menu extends Validate
{
    /**
     * 定义验证规则
     * 格式：'字段名' =>  ['规则1','规则2'...]
     *
     * @var array
     */
    protected $rule = [
        'name' => 'require',
        //'name' => 'require|checkUniqueWithSoftDelete:name',
        'controller' => 'require|checkUniqueWithSoftDelete:controller',

        'code' => 'checkDerivedValue',
        'route_name' => 'checkDerivedValue',
        'route_path' => 'checkDerivedValue',
        'route_path_full' => 'checkDerivedValue',
        'component' => 'require|checkUniqueWithSoftDelete:component|checkDerivedValue',
        'table_name' => 'checkDerivedValue',
        'key' => 'checkDerivedValue',

    ];

    /**
     * 定义错误信息
     * 格式：'字段名.规则名' =>  '错误信息'
     *
     * @var array
     */
    protected $message = [
        //'name.checkUniqueWithSoftDelete' => '菜单名已存在！',
        'controller.checkUniqueWithSoftDelete' => '控制器已存在！',
        'component.checkUniqueWithSoftDelete' => '组件已存在！',

        'code.checkDerivedValue' => '权限标识符不合法',
        'route_name.checkDerivedValue' => '路由名称不合法',
        'route_path.checkDerivedValue' => '路由地址不合法',
        'route_path_full.checkDerivedValue' => '完整路由地址不合法',
        'component.checkDerivedValue' => '组件名称不合法！',
        'table_name.checkDerivedValue' => '表名不合法',
        'key.checkDerivedValue' => '语言标识符不合法',

    ];

    // 定义场景：新增和更新操作
    protected $scene = [
        'add' => ['name', 'controller', 'component', 'code', 'route_name', 'route_path', 'route_path_full', 'table_name', 'key'],
        'edit' => ['name', 'controller', 'component', 'code', 'route_name', 'route_path', 'route_path_full', 'table_name', 'key'],
        'index' => ['*'], // 修改为 '*' 表示不验证任何字段
    ];

    // 通过 Controller 导出 各个菜单信息
    private ?array $derivedInfoCache = null;
    protected function checkDerivedValue($value,$rule,$data):bool
    {
        // 只有菜单才检查这些派生属性
        if($data['type'] != Constants::MENU_TYPE_MENU) {
            return true;
        }
        if($this->derivedInfoCache === null) {
            if($data['controller'] === ''){
                $this->derivedInfoCache = [
                    'code'           => '',
                    'route_name'     => '',
                    'route_path'     => '',
                    'route_path_full'=> '',
                    'component'      => '',
                    'table_name'     => '',
                    'key'            => '',
                ];
            } else {
                $parts = explode('/', $data['controller']);
                $kababParts = array_map([Str::class,'snake'], $parts,array_fill(0, count($parts), '-'));
                $snakeParts = array_map([Str::class,'snake'], $parts,array_fill(0, count($parts), '_'));
                $pascalParts = array_map('ucfirst', $parts);
                $this->derivedInfoCache = [
                    'code'           => implode(':', $kababParts) . ':*',
                    'route_name'     => implode('', $pascalParts),
                    'route_path'     => end($kababParts),
                    'route_path_full'=> '/' . implode('/', $kababParts),
                    'component'      => implode('/',$kababParts) .'/index',
                    'table_name'     => implode('_', $snakeParts),
                    'key'            => 'menu.' . implode('.', $kababParts) . '.title',
                ];
            }
        }
        if($rule) {
            $expectedValue = $this->derivedInfoCache[$rule];
            return $value === $expectedValue;
        } else {
            return true;
        }
    }


    // 自定义验证方法：检查菜单名称唯一性（排除软删除数据）
    protected function checkUniqueWithSoftDelete($value, $ruleField, $data, $field): bool
    {
        // 当为更新操作且存在ID时，检查字段是否被修改
        if (!empty($data['id'])) {
            $originalData = MenuModel::where('id', $data['id'])->find();
            // 若字段值未变化，则跳过唯一性校验
            if ($originalData && $originalData[$ruleField] == $value) {
                return true;
            }
        }

        // 构建查询条件（排除软删除及当前记录）
        $query = MenuModel::where(function ($q) use ($ruleField, $value) {
            $q->whereNull('delete_time')->where($ruleField, '=', $value);
        });

        // 编辑时排除自身记录（需确保 $data['id'] 存在）
        if (array_key_exists('id', $data) && !empty($data['id'])) {
            $query->where('id', '<>', $data['id']);
        }
        // 仅检查 app='admin'
        $query->where('app', '=', 'admin');
        // trace($query->buildSql());
        return $query->count() === 0;
    }
}
